;====================================================================
;
; Ogre3D Wrapper for Blitz3D
;
; Ogre::Root
;
;====================================================================

; Rendering Subsystems
Const RSS_DIRECT3D9				= 1
Const RSS_OPENGL				= 2
Const RSS_DIRECT3D9_D			= 3
Const RSS_OPENGL_D				= 4


; Transformationspace
Const TS_LOCAL					= 1
Const TS_PARENT					= 2
Const TS_WORLD					= 3

; SceneTypes
Const ST_GENERIC				= 1
Const ST_EXTERIOR_CLOSE			= 2
Const ST_EXTERIOR_FAR			= 4
Const ST_EXTERIOR_REAL_FAR		= 8
Const ST_INTERIOR				= 16

; ShadowTypes
Const ST_NONE					= 0
Const ST_STENCIL_MOD			= 18
Const ST_STENCIL_ADD 			= 17
Const ST_TEX_MOD				= 34
Const ST_TEX_ADD 				= 33

Type TColor
	Field r#
	Field g#
	Field b#
	Field a#
End Type

Type TVector3
	Field x#
	Field y#
	Field z#
End Type

Type TQuaternion
	Field w#
	Field x#
	Field y#
	Field z#
End Type
Global quat.TQuaternion = New TQuaternion

Global vector% = CreateBank(12)
Global quaternion% = CreateBank(16)


Type TResourceLocations
	Field location$
End Type


Type TRoot
	; Ogre3D Pointers
	Field ogre_root%
	Field ogre_rendersystem%
	Field ogre_win%
	Field ogre_scenemanager%
	Field ogre_resgrpmanager%
	Field ogre_viewport%
	Field ogre_rootscenenode%
	Field ogre_compositionmanager%
	
	; Settings
	Field ogre_rss%						; Rendering Subsystem
	Field ogre_plugins$					; Path to the plugins.cfg
	Field ogre_config$					; Path to the config.cfg
	Field ogre_log$						; Path to the ogre.log
	Field title$						; Apptitle
	; save Resource Locations
	Field ogre_resources.TResourceLocations
	
	; Bullet
	Field bullet%	Field world%
	Field gravX#, gravY#, gravZ#
End Type
Global ogre3d.TRoot = New TRoot

; default gravity values
ogre3d\gravX = 0.0
ogre3d\gravY = -9.81
ogre3d\gravZ = 0.0


Function AppTitle(title$)
	ogre3d\title = title
End Function

Function genEntityName$(prefix$ = "entity_")
	Return prefix$ + Str(ogre_entity_count)
End Function

Function SetRenderer(renderingSubSystem% = RSS_DIRECT3D9)
	ogre3d\ogre_rss = renderingSubSystem
End Function

Function SetPluginsConfig(pluginCfgFile$ = "plugins.cfg")
	ogre3d\ogre_plugins = pluginCfgFile
End Function

Function SetConfigFile(configFile$ = "ogre.cfg")
	ogre3d\ogre_config = configFile
End Function

Function SetLogFile(logFile$ = "ogre.log")
	ogre3d\ogre_log = logFile
End Function

Function ResourceLocationExists%(location$)
	Local found% = False
	For ogre3d\ogre_resources.TResourceLocations = Each TResourceLocations
		If ogre3d\ogre_resources\location = location
			found = True
			Exit
		End If
	Next
	
	Return found
End Function

Function AddResourceLocation(location$)
	ogre3d\ogre_resources = New TResourceLocations
	ogre3d\ogre_resources\location = location
End Function

Function OgreGraphics3D(width%, height%, depth% = 32, fullscreen% = False, vsync% = False)
	
	If ogre3d\title = "" Then ogre3d\title = "bo3D"
	If ogre3d\ogre_plugins = "" Then ogre3d\ogre_plugins = "plugins.cfg"
	If ogre3d\ogre_config = "" Then ogre3d\ogre_config = "ogre.cfg"
	If ogre3d\ogre_log = "" Then ogre3d\ogre_log = "ogre.log"
	If ogre3d\ogre_rss < 1 Then ogre3d\ogre_rss = RSS_DIRECT3D9
	
	mode% = 2
	If fullscreen = True Then mode% = 1
	Graphics3D(width, height, depth, mode)
	
	; get the Ogre::Root Handle
	ogre3d\ogre_root = o_newRoot(ogre3d\ogre_plugins, ogre3d\ogre_config, ogre3d\ogre_log, True)
	
	Local rss_name$ = "Direct3D9 Rendering Subsystem"
	
	Select ogre3d\ogre_rss
		Case RSS_DIRECT3D9	: rss_name = "Direct3D9 Rendering Subsystem"
		Case RSS_OPENGL		: rss_name = "OpenGL Rendering Subsystem"
	End Select
	
	Local hWnd%		= SystemProperty("AppHWND")
	
	Local v$ = "false"
	If vsync = True Then v = "true"
	Local tags$ = "externalWindowHandle|" + Str(hWnd) + "|left|0|top|0|vsync|" + v
	
	; get the Handle to the RenderSystem
	ogre3d\ogre_rendersystem 	= o_getRenderSystemByName(ogre3d\ogre_root, rss_name)
	o_setRenderSystem(ogre3d\ogre_root, ogre3d\ogre_rendersystem)
	
	ogre3d\ogre_win 			= o_initialise(ogre3d\ogre_root, 0, title, "")
	ogre3d\ogre_win 			= o_createRenderWindow(ogre3d\ogre_root, title, width, height, fullscreen, tags)
	ogre3d\ogre_scenemanager 	= o_createSceneManager(ogre3d\ogre_root, ST_GENERIC, "sceneManager")
	ogre3d\ogre_rootscenenode	= o_getRootSceneNode(ogre3d\ogre_scenemanager)
	o_createResourceGroup("bo3D", True)
	
	; initialise Bullet
	ogre3d\bullet 	= initBullet(ogre3d\gravX, ogre3d\gravY, ogre3d\gravZ)
	ogre3d\world	= getDynamicsWorld(ogre3d\bullet)
	
End Function

Function StopOgre3D()
	o_freeRoot(ogre3d\ogre_root)
	FreeBank(vector)
	FreeBank(quaternion)
End Function

Function getPath$(fullPath$)
	fullPath 		= Replace(fullPath, "/", "\")
	Local path$		= fullPath
	Local l%		= Len(fullPath)
	Local lastSlash%= 1
	
	For i% = 1 To l
		Local c$ = Mid(fullPath, i, 1)
		If c$ = "\" Then lastSlash = i
	Next
	
	If lastSlash > 1 And lastSlash < Len(fullPath)
		path = Left(fullPath, lastSlash - 1)
	EndIf
	
	If l = Len(path) Then path = ""
	
	Return path
End Function

Function getFileName$(fullPath$)
	fullPath 		= Replace(fullPath, "/", "\")
	Local file$		= fullPath
	Local l%		= Len(fullPath)
	Local lastSlash%= 1
	
	For i% = 1 To l
		Local c$ = Mid(fullPath, i, 1)
		If c$ = "\" Then lastSlash = i
	Next
	
	If lastSlash > 1 And lastSlash < Len(fullPath)
		file = Right(fullPath, l - lastSlash)
	EndIf
	
	Return file
End Function

Function SkyBox(filename$)
	Local path$ 		= getPath(filename)
	Local file$ 		= getFileName(filename)
	Local filesystem$	= "FileSystem"
	Local ext$			= Lower(Right(path, 4))
	
	Select ext
		Case ".zip", ".dat", ".pak"	: filesystem = "Zip" : path = Left(path, Len(path) - 4)
	End Select
	
	If ResourceLocationExists(path) = False
		o_addResourceLocation(path, filesystem, "bo3D", True)
		o_initialiseResourceGroup("bo3D")
		
		AddResourceLocation(path)
	EndIf
	
	If Lower(Right(filename, 9)) = ".material" Then filename = Left(filename, Len(filename) - 9)
	
	o_setSkyBox(ogre3d\ogre_scenemanager, True, filename, 1000, True, 0, "bo3D")
End Function

Function SetMediaDir(directory$, recursive% = True)
	Local filesystem$	= "FileSystem"
	Local ext$			= Lower(Right(directory, 4))
	
	Select ext
		Case ".zip", ".dat", ".pak"	: filesystem = "Zip" : directory = Left(directory, Len(directory) - 4)
	End Select
	
	If ResourceLocationExists(directory) = False
		o_addResourceLocation(directory, filesystem, "bo3D", recursive)
		o_initialiseResourceGroup("bo3D")
		
		AddResourceLocation(directory)
	EndIf
End Function

Function ShadowStyle(style% = ST_TEX_ADD)
	o_setShadowTechnique(ogre3d\ogre_scenemanager, style)
	o_setShadowTextureSize(ogre3d\ogre_scenemanager, 512)
	o_sm_setShadowFarDistance(ogre3d\ogre_scenemanager, 100.0)
End Function

Function ShadowTexSize(texture_size% = 512)
	o_setShadowTextureSize(ogre3d\ogre_scenemanager, texture_size)
End Function

Function RenderWorld(time_since_last_frame# = 0.0)
	o_renderOneFrame(ogre3d\ogre_root, time_since_last_frame)
End Function

Function SetGravity(gravX# = 0.0, gravY# = -9.81 , gravZ# = 0.0)
	ogre3d\gravX = gravX
	ogre3d\gravY = gravY
	ogre3d\gravZ = gravZ
End Function


Function UpdateWorld()
	updateBullet(ogre3d\bullet, 0.01666, 1, 0.01666)
	
	For ent.TEntity = Each TEntity
		If ent\rbody <> 0
			Local v% = bb_getRigidBodyPosition(ent\rbody)
			CopyMemory(vector, v, 12)
			
			Local x# = PeekFloat(vector, 0)
			Local y# = PeekFloat(vector, 4)
			Local z# = PeekFloat(vector, 8)
			
			PositionEntity(Handle(ent), x, y, -z)
			
			v = bb_getRigidBodyRotation(ent\rbody)
			CopyMemory(quaternion, v, 16)
			
			quat\w = PeekFloat(quaternion, 0)
			quat\x = PeekFloat(quaternion, 4)
			quat\y = PeekFloat(quaternion, 8)
			quat\z = PeekFloat(quaternion, 12)
			
			o_scenenode_setOrientation(o_entity_getParentSceneNode(ent\ptr), quat)
		EndIf
	Next
	
End Function


;~IDEal Editor Parameters:
;~F#3B#65#69#6D#71#75#79#85#BC#D0#E2#F8
;~C#Blitz3D